import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

/**
 * Class for managing stylesheets. Stylesheets are loaded into named slots so that they can be
 * removed or changed later.
 */
@Injectable()
export class StyleManagerService {
  private themeStorageKey = 'docs-theme-storage-current-key';

  private themeKeySubject = new BehaviorSubject<string>(null);

  themeKeyObservable = this.themeKeySubject.asObservable();

  /**
   * Set the stylesheet with the specified key.
   */
  setStyle(key: string, href: string) {
    getLinkElementForKey(key).setAttribute('href', href);
  }

  /**
   * Remove the stylesheet with the specified key.
   */
  removeStyle(key: string) {
    const existingLinkElement = getExistingLinkElementByKey(key);
    if (existingLinkElement) {
      document.head.removeChild(existingLinkElement);
    }
  }

  /**
   * Store the theme key in localStorage.
   */
  storeTheme(key: string) {
    try {
      window.localStorage.setItem(this.themeStorageKey, key);
      this.themeKeySubject.next(key);
    } catch { }
  }

  /**
   * Get the theme key from localStorage.
   */
  getStoredThemeKey(): string | null {
    try {
      return window.localStorage[this.themeStorageKey] || null;
    } catch {
      return null;
    }
  }
}

const getLinkElementForKey = (key: string) => getExistingLinkElementByKey(key) || createLinkElementWithKey(key);

const getExistingLinkElementByKey = (key: string) => document.head.querySelector(`link[rel="stylesheet"].${getClassNameForKey(key)}`);

const createLinkElementWithKey = (key: string) => {
  const linkEl = document.createElement('link');
  linkEl.setAttribute('rel', 'stylesheet');
  linkEl.classList.add(getClassNameForKey(key));
  document.head.appendChild(linkEl);
  return linkEl;
};

const getClassNameForKey = (key: string) => `style-manager-${key}`;
